package com.shanghaionstar.smart.service;

import android.content.Context;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.onstar.cn.api.AuthQRCodeService;
import com.onstar.cn.api.UsersService;
import com.onstar.cn.auth.userProfile.Vehicle;
import com.onstar.cn.common.exception.OnStarException;
import com.onstar.cn.common.util.Constants;
import com.onstar.cn.common.util.DeviceUtil;

import com.onstar.cn.common.util.PreferencesUtls;
import com.onstar.cn.framework.annotation.http.HeadsValue;
import com.onstar.cn.framework.annotation.http.Request;
import com.onstar.cn.framework.mvp.base.core.BaseService;
import com.onstar.cn.framework.network.HttpInjectUtils;
import com.onstar.cn.framework.network.entity.RequestEntity;
import com.onstar.cn.framework.network.enumtype.HttpAccept;
import com.onstar.cn.framework.network.enumtype.HttpMethod;
import com.onstar.cn.framework.network.enumtype.Language;
import com.onstar.cn.framework.utils.GsonHelper;
import com.onstar.cn.mag.LocalVehicleEntity;
import com.onstar.cn.smart.BaseResponse;
import com.onstar.cn.smart.ControlSmartDeviceResponse;
import com.onstar.cn.smart.GetSmartDeviceDetailResponse;
import com.onstar.cn.smart.SmartDevicesResponse;
import com.onstar.cn.smart.SmartTokenResponse;
import com.onstar.cn.smart.entity.GeoFencingEntity;
import com.onstar.cn.smart.entity.ServiceItem;
import com.onstar.cn.smart.request.LoginAuthInfo;
import com.shanghaionstar.enumtype.FunctionNameFindId;
import com.shanghaionstar.utils.ApplicationUtil;
import com.shanghaionstar.utils.BusinessUtil;
import com.shanghaionstar.utils.FinalConstants;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import rx.Observable;
import rx.functions.Func0;

/**
 * Created by 7828wc on 16/7/21.
 */
public class SmartHomeService extends BaseService<Object> {

    private Context context;

    @Override
    public RequestEntity getRequestEntity() {
        return null;
    }

    @Override
    public Object jsonToBean(String json) {
        return null;
    }

//    private static class RequestUtilInner {
//        static SmartRequestUtil requestUtil = new SmartHomeService();
//    }
//
//
//    public final static SmartHomeService getInstance() {
//        return RequestUtilInner.requestUtil;
//    }
//
//    private SmartHomeService(){}

    public SmartHomeService(Context context) {
        this.context = context;
    }

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.GET)
    public String getSmartDevicesJson() throws OnStarException {
        UsersService service = new UsersService(
                Constants.CURRENT_SERVER_URL);
        Vehicle vehicle = ApplicationUtil.getInstance().getCurrentVehicle();
        RequestEntity requestEntity = service.getSmartDevices(ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), vehicle == null ? "" : vehicle.getVin());
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "getSmartDevicesJson", requestEntity);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }

    public Observable<SmartDevicesResponse> getSmartDevices() {
        return Observable.defer(new Func0<Observable<SmartDevicesResponse>>() {
            @Override
            public Observable<SmartDevicesResponse> call() {
                try {
                    return Observable.just(GsonHelper.fromJson(getSmartDevicesJson(),SmartDevicesResponse.class));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }


    private void addAuthorization(Context context, RequestEntity requestEntity) {
        LinkedHashMap<String, Object> coHashMap = new LinkedHashMap<String, Object>();
        coHashMap.put(FinalConstants.HTTP_AUTHORIZATION, ApplicationUtil.getInstance().getToken());
        requestEntity.setCustomHeads(coHashMap);
    }

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.GET)
    public String getSmartDeviceDetailJson(String deviceId, String deviceType) throws OnStarException {
        UsersService service = new UsersService(
                Constants.CURRENT_SERVER_URL);
        Vehicle vehicle = ApplicationUtil.getInstance().getCurrentVehicle();
        RequestEntity requestEntity = service.getSmartDeviceDetail(ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), vehicle == null ? "" : vehicle.getVin(), deviceId, deviceType);
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "getSmartDeviceDetailJson", requestEntity, String.class, String.class);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }


    public Observable<GetSmartDeviceDetailResponse> getSmartDeviceDetail(final String deviceId, final String deviceType) {
        return Observable.defer(new Func0<Observable<GetSmartDeviceDetailResponse>>() {
            @Override
            public Observable<GetSmartDeviceDetailResponse> call() {
                try {

                    return Observable.just(new Gson().fromJson(getSmartDeviceDetailJson(deviceId, deviceType), GetSmartDeviceDetailResponse.class));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.PUT)
    public String bindDeviceJson(String deviceId) throws OnStarException {
        UsersService service = new UsersService(
                Constants.CURRENT_SERVER_URL);
        Vehicle vehicle = ApplicationUtil.getInstance().getCurrentVehicle();
        RequestEntity requestEntity = service.bindDevice(ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), vehicle == null ? "" : vehicle.getVin(), deviceId);
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "bindDeviceJson", requestEntity, String.class);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }

    public Observable<String> bindDevice(final String deviceId) {
        return Observable.defer(new Func0<Observable<String>>() {
            @Override
            public Observable<String> call() {
                try {
                    return Observable.just(bindDeviceJson(deviceId));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.PUT)
    public String unBindDeviceJson(String deviceId) throws OnStarException {
        UsersService service = new UsersService(
                Constants.CURRENT_SERVER_URL);
        Vehicle vehicle = ApplicationUtil.getInstance().getCurrentVehicle();
        RequestEntity requestEntity = service.unBindDevice(ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), vehicle == null ? "" : vehicle.getVin(), deviceId);
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "unBindDeviceJson", requestEntity, String.class);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }

    public Observable<String> unBindDevice(final String deviceId) {
        return Observable.defer(new Func0<Observable<String>>() {
            @Override
            public Observable<String> call() {
                try {
                    return Observable.just(unBindDeviceJson(deviceId));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

//    ControlSmartDeviceResponse

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.PUT)
    public String controlSmartDeviceJson(RequestEntity entity) throws OnStarException {
        UsersService service = new UsersService(
                Constants.CURRENT_SERVER_URL);
        Vehicle vehicle = ApplicationUtil.getInstance().getCurrentVehicle();
        RequestEntity requestEntity = service.controlSmartDevice(entity, ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), vehicle == null ? "" : vehicle.getVin());
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "controlSmartDeviceJson", requestEntity, RequestEntity.class);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }

    public Observable<ControlSmartDeviceResponse> controlSmartDevice(final RequestEntity entity) {
        return Observable.defer(new Func0<Observable<ControlSmartDeviceResponse>>() {
            @Override
            public Observable<ControlSmartDeviceResponse> call() {
                try {
                    return Observable.just(new Gson().fromJson(controlSmartDeviceJson(entity), ControlSmartDeviceResponse.class));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

//    GeoFencingEntity

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.PUT)
    public String saveSmartGeoFencingJson(String deviceId, RequestEntity entity) throws OnStarException {
        UsersService service = new UsersService(
                Constants.CURRENT_SERVER_URL);
        Vehicle vehicle = ApplicationUtil.getInstance().getCurrentVehicle();
        RequestEntity requestEntity = service.saveSmartGeoFencing(entity, ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), vehicle == null ? "" : vehicle.getVin(), deviceId);
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "saveSmartGeoFencingJson", requestEntity, String.class, RequestEntity.class);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }

    public Observable<GeoFencingEntity> saveSmartGeoFencing(final String deviceId, final RequestEntity entity) {
        return Observable.defer(new Func0<Observable<GeoFencingEntity>>() {
            @Override
            public Observable<GeoFencingEntity> call() {
                try {
                    return Observable.just(GsonHelper.fromJson( saveSmartGeoFencingJson(deviceId, entity),GeoFencingEntity.class));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.PUT)
    public String batchSmartGeoFencingJson(RequestEntity entity) throws OnStarException {
        UsersService service = new UsersService(
                Constants.CURRENT_SERVER_URL);
        Vehicle vehicle = ApplicationUtil.getInstance().getCurrentVehicle();
        RequestEntity requestEntity = service.batchApplySmartDeviceGeofencing(entity, ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), vehicle == null ? "" : vehicle.getVin());
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "batchSmartGeoFencingJson", requestEntity, RequestEntity.class);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }

    public Observable<GeoFencingEntity> batchSmartGeoFencing(final RequestEntity entity) {
        return Observable.defer(new Func0<Observable<GeoFencingEntity>>() {
            @Override
            public Observable<GeoFencingEntity> call() {
                try {
                    return Observable.just(GsonHelper.fromJson(batchSmartGeoFencingJson(entity),GeoFencingEntity.class));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.GET)
    public String localVehicleServiceJson(LocalVehicleEntity entity) throws OnStarException {
        UsersService service = new UsersService(
                Constants.CURRENT_SERVER_URL);
        RequestEntity requestEntity = service.localVehicleService(entity, ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), ApplicationUtil.getInstance().getCurrentVehicle().getVin());
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "localVehicleServiceJson", requestEntity, LocalVehicleEntity.class);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }

    public Observable<String> localVehicleService(final LocalVehicleEntity entity) {
        return Observable.defer(new Func0<Observable<String>>() {
            @Override
            public Observable<String> call() {
                try {
                    return Observable.just(localVehicleServiceJson(entity));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.GET)
    public String getServiceStatusJson(RequestEntity entity, String smartHome) throws OnStarException {
        UsersService service = new UsersService(
                Constants.CURRENT_SERVER_URL);
        Vehicle vehicle = ApplicationUtil.getInstance().getCurrentVehicle();
        RequestEntity requestEntity = service.getServiceStatus(entity, ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), vehicle == null ? "" : vehicle.getVin(), smartHome);
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "getServiceStatusJson", requestEntity, RequestEntity.class, String.class);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }

    //     List<ServiceItem> items = new Gson().fromJson(json, new TypeToken<ArrayList<ServiceItem>>() {
//}.getType());
    public Observable<List<ServiceItem>> getServiceStatus(final RequestEntity entity, final String smartHome) {
        return Observable.defer(new Func0<Observable<List<ServiceItem>>>() {
            @Override
            public Observable<List<ServiceItem>> call() {
                try {
                    List<ServiceItem> items = new Gson().fromJson(getServiceStatusJson(entity, smartHome), new TypeToken<ArrayList<ServiceItem>>() {
                    }.getType());
                    return Observable.just(items);
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.GET)
    public String getTokenJson(RequestEntity entity) throws OnStarException {
        UsersService service = new UsersService(
                Constants.CURRENT_SERVER_URL);
        Vehicle vehicle = ApplicationUtil.getInstance().getCurrentVehicle();
        RequestEntity requestEntity = service.getToken(entity, ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), vehicle == null ? "" : vehicle.getVin());
//        RequestEntity requestEntity = service.getToken(entity, ApplicationUtil.getInstance().getIdpID(), ApplicationUtil.getInstance().getAccountId(), vehicle == null ? "" : vehicle.getVin(), deviceId);
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "getTokenJson", requestEntity, RequestEntity.class);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }

    public Observable<SmartTokenResponse> getToken(final RequestEntity entity) {
        return Observable.defer(new Func0<Observable<SmartTokenResponse>>() {
            @Override
            public Observable<SmartTokenResponse> call() {
                try {
//                    (SmartTokenResponse.class)JsonParseUtil.JsonToBean(SmartTokenResponse.class, getTokenJson(entity))
                    return Observable.just(GsonHelper.fromJson( getTokenJson(entity),SmartTokenResponse.class));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }


    @Request(heads = @HeadsValue(accept = HttpAccept.JSON, language = Language.AUTO), method = HttpMethod.PUT)
    public String authQRCodeJson(RequestEntity entity,String qrCode) throws OnStarException {
        AuthQRCodeService service = new AuthQRCodeService(Constants.CURRENT_SERVER_URL);
        LoginAuthInfo authInfo = new LoginAuthInfo();
        authInfo.setAccessToken(ApplicationUtil.getInstance().getToken());
        String idToken = PreferencesUtls.getInstance(context).getString(Constants.ID_TOKEN);
        authInfo.setiDToken(TextUtils.isEmpty(idToken) ? "" : idToken);
        authInfo.setMobileDeviceID(new DeviceUtil(context).getDeviceID());
        authInfo.setMobileDeviceToken("123");
        authInfo.setqRCode(qrCode);
        authInfo.setFunctionID(FunctionNameFindId.Mobile_ScanBarCode_Success.getStringValue());
        authInfo.setAccessToken(ApplicationUtil.getInstance().getToken());
        RequestEntity requestEntity = service.authQRCode(entity,authInfo,qrCode);
        addAuthorization(context, requestEntity);
        requestEntity = HttpInjectUtils.injectHttp(SmartHomeService.this.getClass(), "authQRCodeJson", requestEntity, RequestEntity.class,String.class);
        return BusinessUtil.getResponse(getDatas(requestEntity), context);
    }

    public Observable<BaseResponse> authQRCode(final RequestEntity entity,final String qrCode) {
        return Observable.defer(new Func0<Observable<BaseResponse>>() {
            @Override
            public Observable<BaseResponse> call() {
                try {
                    String result = authQRCodeJson(entity,qrCode);
                    return Observable.just(GsonHelper.fromJson(result,BaseResponse.class));
                } catch (OnStarException e) {
                    return Observable.error(e);
                }
            }
        });
    }

}
